import { addHistory } from "../utils/history/history";
import { getEngineVal } from "../../views/Functions/children/Engine/Engine";
import { toast } from "../../components/Toast/Toast";
import { KeywordListType } from "../domain/keyword";
import { keywordApi } from "../backend/server";
import { ping } from "./ping";

const toShortcut = (url: string) => {
  if (/^http/.test(url)) location.href = url;
  else location.href = "http://" + url;
};

// Define a type for a list of objects with a key and url property
// export type keywordListType = Array<{
//   id: string;
//   keyName: string;
//   url: string;
// }>;

// Declare a variable to hold a list of keywords
let keywordList: KeywordListType = [];

// Define a function to return the keyword list
// export function getKeywordList() {
//   return keywordList;
// }

// Define a function to update the keyword list

/**
 *  strip the first cmd + space that met.
 * @param cmd eg. baidu dick
 * @returns dick
 */
export const stripSearchEngineHead = (cmd: string) => {
  // return cmd.substring(cmd.indexOf(" ") + 1);
  return cmd.replace(/^(baidu|sougou|google|g) /, "");
};

// Fetch the list of placeholders from the backend and update the keyword list
//read keyword list from cache
// const cachedKeywordList = localStorage.getItem("keywordList");
// if (cachedKeywordList) {
//   try {
//     keywordList = JSON.parse(cachedKeywordList);
//   } catch (e) {
//     // message.error("error: ");
//     addMes(
//       "error: try to parse keyword list from local cache, reason: unresolved string!"
//     );
//   }
// }
//update cache keyword list

// export const refreshKeywordList = async () => {
//   const {
//     data: { list },
//   } = await keywordApi.fetchPlaceholders();
//   keywordList = list;
//   localStorage.setItem("keywordList", JSON.stringify(keywordList));
// };

type CmdHandlerType = (val: string, clearInputCallBack?: () => void) => void;
type CommandType = {
  cmd: RegExp;
  handler: CmdHandlerType;
};
// Define an array of command objects with a cmd property and a handler function
const command: CommandType[] = [
  {
    // If the input starts with a space, load the corresponding plugin
    cmd: /^ /,
    handler(val, clearInputCallBack) {
      val = val.replace(" ", "");
      import(`../plugins/plugin_${val.split(" ")[0]}.ts`)
        .then(
          (res: {
            install: (
              val: string,
              keywordList: KeywordListType,
              clearInputCallBack?: () => void
            ) => void;
          }) => {
            res.install(val, keywordList, clearInputCallBack);
          }
        )
        .catch((err) => {
          console.log(err);
          // try to resolve it as windows command
          location.href = "cmd://" + val;
        });
    },
  },
  {
    // match custom protocol including http:// or https://
    cmd: /.*?:\/\/.+/,
    handler(val) {
      // extract url from input
      let url: RegExpExecArray | null = new RegExp(
        /(http|https):\/\/.*/ //[a-z\.\/%0-9A-Z#&-]*
      ).exec(val);
      if (url) location.href = url[0];
      else location.href = val;
    },
  },
  // {
  //   // If the input contains http:// or https://, open the corresponding URL
  //   cmd: /(http|https):\/\//,
  //   handler(val) {
  //     let url: RegExpExecArray | null = new RegExp(
  //       /(http|https):\/\/.*/ //[a-z\.\/%0-9A-Z#&-]*
  //     ).exec(val);
  //     if (url) window.open(url[0]);
  //     else encryptAndForward(localStorage.getItem("searchEngine"), val);
  //   },
  // },
  {
    // If the input starts with "sougou ", search on sougou
    cmd: /^(sougou |s )/,
    handler(val) {
      encryptAndForward(stripSearchEngineHead(val), "sougou");
    },
  },
  {
    // If the input starts with "baidu ", search on Baidu
    cmd: /^(baidu )/,
    handler(val) {
      encryptAndForward(stripSearchEngineHead(val), "baidu");
    },
  },

  {
    // If the input starts with "google ", search on Google
    cmd: /^(google |g )/,
    handler(val) {
      // if (val.startsWith("g ")) val = val.replace("g ", "");
      encryptAndForward(stripSearchEngineHead(val), "google");
    },
  },
  {
    // If the input starts with "bilibili ", search on bilibili
    cmd: /^(bilibili |b )/,
    handler(val) {
      location.href = `https://search.bilibili.com/all?keyword=${encodeURIComponent(
        //val.replace("bilibili ", "")
        // val.substring(val.indexOf(" ") + 1)
        // stripCmdHead(val)
        val.replace(/^bilibili /, "").replace(/^b /, "")
      )}`;
    },
  },
  // {
  //   // If the input contains Chinese characters, search on Baidu
  //   cmd: /[\u2E80-\uFE4F]/,
  //   handler(val) {
  //     encryptAndForward("baidu", val);
  //   },
  // },
  {
    // If the input matches none of the above commands, search using the default search engine
    cmd: /.+/,
    handler(val) {
      // let shortcut =
      //   keywordList && keywordList.find((ele) => ele.keyName === val)?.url;
      // ping("/access/test").catch((err) => {
      //   encryptAndForward(val);
      // });
      // encryptAndForward(val);

      (async () => {
        try {
          const { data } = await keywordApi.findByKey(val);
          keywordApi.updateRanks(data); // upgrade keyword ranks
          if (data === null) return encryptAndForward(val);
          toShortcut(data.url);
        } catch (err) {
          encryptAndForward(val);
        }
      })();

      // .then(({ data }) => {
      // });
      // shortcut ? toShortcut(shortcut) : encryptAndForward(val);
    },
  },
  {
    // if you press enter directly with no input, it will return clipboard for you.
    cmd: /.*/,
    handler(_) {
      navigator.clipboard.readText().then((val) => {
        if (val.startsWith("http")) {
          window.location.href = val;
        } else {
          encryptAndForward(val);
        }
      });
    },
  },
];

// Encode the input and forward it to the corresponding search engine
function encryptAndForward(val: string, engine?: string) {
  addHistory(val);
  const searchUrl = getEngineVal(engine);
  window.location.href = searchUrl.replace("@", encodeURIComponent(val));
}

// Define a function to execute the appropriate command based on the input
export function goto(
  wd: string,
  keywordNewList: KeywordListType,
  clearInputCallBack?: () => void
): void {
  keywordList = keywordNewList;
  // Find the first command that matches the input and execute its handler function
  const cmd = command.find((val) =>
    new RegExp(val.cmd).test(wd)
  ) as unknown as CommandType;

  try {
    cmd.handler(wd, clearInputCallBack);
  } catch (err) {
    toast("unknown error!");
  }
}
